# -*- mode: python -*-
###
#
# (c) 2000-2007 Wijnand Modderman <wijnand at tehmaze dot com>
# All rights reserved. See docs/LICENSE
#
###

# system imports
import sys
import os
import traceback

# DDB imports
from ddb.log import log, logException
from ddb.lang import lang
from ddb.event import event
from ddb.access import AccessException
from ddb.register import register

# DDB exports satisfaction
EXPORT=[]

class messageCommands:

    def __init__(self):
        self.reg = register.init(self)

    def onLoad(self, e):
        log.msg('Bot loaded')

    def onMessage(self, e):
        command = None
        if e.transport.usePrefix:
            ctx    = [e.transport.type, e.transport.name, e.target.lower()]
            prefix = self.reg.get('prefix', *ctx)
            if not prefix:
                prefix = '!'
            else:
                prefix = prefix[0]
            if e.message.startswith(prefix):
                command = e.message[len(prefix):]
        else:
            command = e.message
        # now check if there is a command, if so, raise an event
        if command:
            if ' ' in command:
                command, args = command.split(' ', 1)
            else:
                args = ''
            command = command.lower()
            # raise new event
            event(e.transport, 'command', user=e.user, command=command, args=args, rawevent=e, target=e.target, commandRegister=self.reg)

class commands:
    def __init__(self):
        self.register = {}
        self.aliases  = {}
        self.flags    = {}

    def _handleException(self, e, ex):
        msg = str(ex)
        try:
            tb = sys.exc_info()[2]
            d  = 1
            while tb.tb_next and d:
                tb = tb.tb_next
                d -= 1
            trace = traceback.extract_tb(tb)
            file  = os.path.basename(trace[0][0])
            line  = trace[0][1]
            msg   = 'Exception in %s[%d]: %s' % (file, line, str(ex))
            e.reply(msg)
            del tb
        finally:
            log.err(msg)

    def _onCommand(self, e):
        e.commands = self
        e.lookups  = [e.command]
        while self.aliases.has_key(e.lookups[-1]):
            e.lookups.append(self.aliases[e.lookups[-1]])
            if len(e.lookups) > 10:
                del self.aliases[e.lookups[0]]
                raise Exception, "circular alias detected, removed"
        try:
            for module in self.register.keys():
                if self.register[module].has_key(e.lookups[-1]):
                    try:
                        log.msg('Hookings command %s with %s' % (e.command, str(e.lookups[-1])), debug=True)
                        self.register[module][e.lookups[-1]](e)
                    except AccessException, ex:
                        log.msg('Access denied for %s to %s' % (str(e.user), e.lookups[-1]))
                        e.reply(lang('access denied'))
                    except Exception, ex:
                        logException(ex, e)
        except Exception, e:
            raise e

    def _onLoadModule(self, e):
        if hasattr(e.module, 'EXPORT'):
            exports = getattr(e.module, 'EXPORT')
            for export in exports:
                if hasattr(e.module, export):
                    # add an instance of this class to the register
                    ref = getattr(e.module, export)()
                    self.register['%s.%s' % (e.name, export)] = {}
                    for x in dir(ref):
                        if not x.startswith('_'):
                            #self.hooks[x] = getattr(ref, x)
                            if x == 'ALIAS':
                                aliases = getattr(ref, x)
                                for alias in aliases.keys():
                                    self.aliases[alias] = aliases[alias]
                            else:
                                hook = getattr(ref, x)
                                if callable(hook):
                                    self.register['%s.%s' % (e.name, export)][x] = hook
                                del hook
                else:
                    log.msg('Could not find exported hook "%s" in "%s"' % (export, e.name))
        else:
            log.msg('Could not find EXPORT in "%s"' % (e.name), debug=True)
        
    def _onReloadModule(self, e):
        oldModuleName = str(e.oldModule.__name__)
        # scan the register for references to this module and remove them
        for module in self.register.keys():
            if module.startswith(oldModuleName):
                del self.register[module]
        self._onLoadModule(e)

    def doc(self, command):
        command = command.lower()
        docs    = []
        for module in self.register.keys():
            if self.register[module].has_key(command):
                hook = self.register[module][command]
                if hasattr(hook, '__doc__'):
                    docs.append(getattr(hook, '__doc__'))
                del hook
        return docs

# instances
command = commands()
mc      = messageCommands()

# exports
bind = (
    ['load',         mc.onLoad,               99],
    ['loadModule',   command._onLoadModule,   99],
    ['reloadModule', command._onReloadModule, 99],
    ['command',      command._onCommand,      99],
    ['message',      mc.onMessage,            80],
    )

# vim:ts=4:sw=4:et:
